#include "common.h"
#include <libgen.h> // 添加basename函数的头文件
#include <sys/select.h>

// 文件发送状态结构体
typedef struct {
    int fd;                     // 文件描述符
    char filename[256];         // 文件名
    size_t filesize;            // 文件总大小
    size_t sent_size;           // 已发送大小
    size_t current_block;       // 当前块索引
    int block_size;             // 块大小
} FileSendState;

// 线程参数结构体
typedef struct {
    int server_fd;              // 服务器socket
    Queue* data_queue;          // 数据队列
    char* filename;             // 文件名
} ThreadArgs;

// 读取线程函数
void* read_thread(void* arg) {
    ThreadArgs* args = (ThreadArgs*)arg;
    int server_fd = args->server_fd;
    Queue* data_queue = args->data_queue;
    char* filename = args->filename;
    
    // 打开文件
    int fd = open(filename, O_RDONLY);
    if (fd < 0) {
        perror("Failed to open file");
        return NULL;
    }
    
    // 获取文件大小
    struct stat st;
    if (fstat(fd, &st) < 0) {
        perror("Failed to get file size");
        close(fd);
        return NULL;
    }
    
    size_t filesize = st.st_size;
    int block_size = BUFFER_SIZE;
    
    // 获取文件基本名称
    char* base_filename = basename(strdup(filename)); // 复制字符串，避免修改原始参数
    
    // 创建文件信息包
    FileInfoPacket info;
    info.type = FILE_INFO;
    strncpy(info.filename, base_filename, sizeof(info.filename) - 1);
    info.filesize = filesize;
    info.block_size = block_size;
    
    // 发送文件信息包
    if (send(server_fd, &info, sizeof(FileInfoPacket), 0) < 0) {
        perror("Failed to send file info");
        close(fd);
        free(base_filename); // 释放复制的字符串
        return NULL;
    }
    
    printf("Sending file: %s (size: %zu bytes)\n", filename, filesize);
    
    // 等待可能的断点续传响应
    fd_set readfds;
    struct timeval tv;
    FD_ZERO(&readfds);
    FD_SET(server_fd, &readfds);
    tv.tv_sec = 1;
    tv.tv_usec = 0;
    
    size_t start_block = 0;
    
    if (select(server_fd + 1, &readfds, NULL, NULL, &tv) > 0) {
        if (FD_ISSET(server_fd, &readfds)) {
            FileResumePacket resume;
            ssize_t recv_size = recv(server_fd, &resume, sizeof(FileResumePacket), 0);
            
            if (recv_size > 0 && resume.type == FILE_RESUME) {
                start_block = resume.last_block + 1;
                printf("Resuming file transfer from block %zu\n", start_block);
                
                // 定位到断点位置
                off_t offset = start_block * block_size;
                if (lseek(fd, offset, SEEK_SET) < 0) {
                    perror("Failed to seek to resume position");
                    close(fd);
                    free(base_filename); // 释放复制的字符串
                    return NULL;
                }
            }
        }
    }
    
    // 创建文件发送状态
    FileSendState state;
    state.fd = fd;
    strncpy(state.filename, base_filename, sizeof(state.filename) - 1);
    state.filesize = filesize;
    state.sent_size = start_block * block_size;
    state.current_block = start_block;
    state.block_size = block_size;
    
    // 释放复制的字符串
    free(base_filename);
    
    // 读取文件并放入队列
    char buffer[BUFFER_SIZE];
    ssize_t bytes_read;
    
    while ((bytes_read = read(fd, buffer, block_size)) > 0) {
        // 创建文件数据包
        FileDataPacket* packet = (FileDataPacket*)malloc(sizeof(FileDataPacket));
        if (!packet) {
            perror("Failed to allocate packet");
            break;
        }
        
        packet->type = FILE_DATA;
        packet->block_index = state.current_block;
        packet->data_size = bytes_read;
        memcpy(packet->data, buffer, bytes_read);
        
        // 放入队列
        queue_push(data_queue, packet, sizeof(FileDataPacket));
        free(packet);
        
        state.current_block++;
        state.sent_size += bytes_read;
        
        // 打印进度
        if (state.current_block % 10 == 0) {
            printf("Sending block %zu (%.2f%%)\n", 
                   state.current_block, 
                   (float)state.sent_size / state.filesize * 100);
        }
    }
    
    // 创建文件结束包
    FileEndPacket end;
    end.type = FILE_END;
    end.total_blocks = state.current_block;
    end.status = 0;
    
    // 放入队列
    queue_push(data_queue, &end, sizeof(FileEndPacket));
    
    printf("File reading completed: %s (%zu bytes)\n", filename, state.sent_size);
    
    close(fd);
    return NULL;
}

// 发送线程函数
void* send_thread(void* arg) {
    ThreadArgs* args = (ThreadArgs*)arg;
    int server_fd = args->server_fd;
    Queue* data_queue = args->data_queue;
    
    while (1) {
        size_t size;
        void* data = queue_pop(data_queue, &size);
        if (!data) continue;
        
        // 处理文件数据包
        if (size == sizeof(FileDataPacket)) {
            FileDataPacket* packet = (FileDataPacket*)data;
            
            // 发送数据包
            if (send(server_fd, packet, sizeof(PacketType) + sizeof(size_t) * 2 + packet->data_size, 0) < 0) {
                perror("Failed to send data packet");
                free(data);
                break;
            }
        }
        // 处理文件结束包
        else if (size == sizeof(FileEndPacket)) {
            FileEndPacket* end = (FileEndPacket*)data;
            
            // 发送结束包
            if (send(server_fd, end, sizeof(FileEndPacket), 0) < 0) {
                perror("Failed to send end packet");
            }
            
            printf("File transfer completed\n");
            free(data);
            break;
        }
        
        free(data);
    }
    
    return NULL;
}

int main(int argc, char* argv[]) {
    if (argc != 3) {
        printf("Usage: %s <server_ip> <filename>\n", argv[0]);
        return 1;
    }
    
    char* server_ip = argv[1];
    char* filename = argv[2];
    
    // 检查文件是否存在
    if (access(filename, F_OK) != 0) {
        perror("File does not exist");
        return 1;
    }
    
    int server_fd;
    struct sockaddr_in server_addr;
    
    // 创建socket
    server_fd = socket(AF_INET, SOCK_STREAM, 0);
    if (server_fd < 0) {
        HANDLE_ERROR("socket failed");
    }
    
    // 设置服务器地址
    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(SERVER_PORT);
    
    if (inet_pton(AF_INET, server_ip, &server_addr.sin_addr) <= 0) {
        HANDLE_ERROR("Invalid address");
    }
    
    // 连接服务器
    if (connect(server_fd, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) {
        HANDLE_ERROR("Connection failed");
    }
    
    printf("Connected to server %s:%d\n", server_ip, SERVER_PORT);
    
    // 创建数据队列
    Queue* data_queue = queue_init();
    
    // 创建线程参数
    ThreadArgs* args = (ThreadArgs*)malloc(sizeof(ThreadArgs));
    if (!args) {
        HANDLE_ERROR("Failed to allocate thread args");
    }
    
    args->server_fd = server_fd;
    args->data_queue = data_queue;
    args->filename = filename;
    
    // 创建读取线程
    pthread_t read_tid;
    if (pthread_create(&read_tid, NULL, read_thread, args) != 0) {
        HANDLE_ERROR("Failed to create read thread");
    }
    
    // 创建发送线程
    pthread_t send_tid;
    if (pthread_create(&send_tid, NULL, send_thread, args) != 0) {
        HANDLE_ERROR("Failed to create send thread");
    }
    
    // 等待线程结束
    pthread_join(read_tid, NULL);
    pthread_join(send_tid, NULL);
    
    // 清理资源
    close(server_fd);
    queue_destroy(data_queue);
    free(args);
    
    return 0;
} 